/// @file S.hh
/// @brief Definition of the SMap and S color handling classes

// *************************************************************************

// Copyright© 2010 Texas A&M University, 
//                 College Station, Texas
//                 Contact: R Crosby <rwc@cs.tamu.edu>
//
// Copyright© 2003, 2004 by BiRC -- Bioinformatics Research Center
//                 University of Aarhus, Denmark
//                 Contact: Thomas Mailund <mailund@birc.dk>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

// *************************************************************************

#ifndef S_HH
#define S_HH

#include <iostream>
#include <string>
#include <set>
#include <map>
#include <vector>

using namespace std;

class SMap;

// *************************************************************************
/// @brief Class to manage the color associated with a named node

class S {

public:

    typedef char colour_t;

    static const colour_t A = 'A';
    static const colour_t B = 'B';
    static const colour_t C = 'C';
    static const colour_t None = ' ';

private:

    const string   _name;
    const unsigned _c;				  // Index into smap vector
    SMap &         _parent;

    S(const string   name, 
      const colour_t c,
      SMap &         parent );

    friend class SMap;

public:

    // accessors 

    const string & Name          () const     { return _name; }
    const colour_t Colour        () const;     
    void           Colour        (const colour_t c) const;
    SMap &         Parent        () const     { return _parent; }

};

ostream & operator<<(ostream &os, const S &s);

// *************************************************************************
/// @brief Mapping class for a set of colors

class SMap {

private:

    vector<S::colour_t> _colors;
    string              _root_label;
    map<string, S*>     _map;

    unsigned            _As;
    unsigned            _Bs;
    unsigned            _Cs;

    void Inc(const S::colour_t c);		  ///< Increment color counters
    void Dec(const S::colour_t c);		  ///< Decrement color counters

    const unsigned SetC(const S::colour_t c)	  ///< Get color vector reference
	{   _colors.push_back(c);
	    return _colors.size()-1; }

    S::colour_t & operator[](const unsigned i) { return _colors[i]; }

    friend class S;

public:

    // Exceptions

    struct AllReadyCreated {
	string name;
	AllReadyCreated(string n) : name(n) {}
    };

    struct NotCreated {
	string name;
	NotCreated(string n) : name(n) {}
    };

    // Methods

    SMap() : _As(0), _Bs(0), _Cs(0) {}
    ~SMap();

    const unsigned        Numberof   (const S::colour_t c);
    S *                   Create     (const char * name) throw(AllReadyCreated);
    S *                   Lookup     (const string name) throw(NotCreated);

    // Reset all symbol-information, clears *everything!* 
    // Currently only used in check programs not in qdist main

    void                  ResetAll   ();

    // Set the coloring for the entire S vector to the specified color

    void                  ColourAll  (const S::colour_t c);

    // Accessors

    vector<S::colour_t> & ColorVector() { return _colors; }              
    string &              RootLabel  () { return _root_label; };
    const unsigned        Size       ()	{ return _map.size(); }

    // Trace/Debug methods

    const void            PrintTable (ostream &os);
    const void            DumpTable  (ostream &os);

};

#endif // S_HH
